package com.bjsxt.controller.doctor;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.bjsxt.controller.BaseController;
import com.bjsxt.domain.Scheduling;
import com.bjsxt.domain.User;
import com.bjsxt.dto.SchedulingDto;
import com.bjsxt.dto.SchedulingFormDto;
import com.bjsxt.dto.SchedulingQueryDto;
import com.bjsxt.service.SchedulingService;
import com.bjsxt.service.UserService;
import com.bjsxt.utils.ShiroSecurityUtils;
import com.bjsxt.vo.AjaxResult;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.aspectj.weaver.loadtime.Aj;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.util.unit.DataUnit;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * @author:liao
 * @Description:TODO 排班相关
 * @date:2021/1/11
 */
@RestController
@RequestMapping("doctor/scheduling")
public class SchedulingController extends BaseController {

    @Reference
    private SchedulingService schedulingService;

    @Autowired
    private UserService userService;

    /**
     * 查询需要排班的医生信息
     * @param userId 医生id
     * @param deptId 科室id 如果科室id为空则表示查询全部科室的
     * @return
     */
    @GetMapping("queryUsersNeedScheduling")
    public AjaxResult queryUsersNeedScheduling(Long userId,Long deptId){
        List<User> users = userService.queryUsersNeedScheduling(userId,deptId);
        return AjaxResult.success(users);
    }


    /**
     * 查询医生的排班信息
     */
    @GetMapping("queryScheduling")
    @HystrixCommand
    public AjaxResult queryScheduling(SchedulingQueryDto schedulingQueryDto){
        // 首先查询出需要排班的医生信息 如果用户id和科室id都为空 那么就查询所有
        List<User> users = userService.queryUsersNeedScheduling(schedulingQueryDto.getUserId(), schedulingQueryDto.getDeptId());
        return getSchedulingAjaxResult(schedulingQueryDto,users);
    }

    /**
     * 查询当前登录医生的排班信息
     */
    @GetMapping("queryMyScheduling")
    @HystrixCommand
    public AjaxResult queryMyScheduling(SchedulingQueryDto schedulingQueryDto){
            // 首先查询出需要排班的医生信息 如果用户id和科室id都为空 那么就查询所有
        List<User> users = userService.queryUsersNeedScheduling(Long.valueOf(ShiroSecurityUtils.getCurrentUser().getUserId().toString()), schedulingQueryDto.getDeptId());
        return getSchedulingAjaxResult(schedulingQueryDto,users);
    }

    /**
     * 构造页面返回数据
     * @param schedulingQueryDto 查询参数类
     * @param users 需要排班的医生信息
     * @return
     */
    private AjaxResult getSchedulingAjaxResult(SchedulingQueryDto schedulingQueryDto, List<User> users) {
        //1.将用户传来的queryDate构造成开始日期和结束日期
        /*
            TODO queryDate有三种情况:
                1.queryDate为空  表示用户在前台点击了当前周 那么就将日期修改为当前时间
                2.queryDate的日期是周一的  表示用户在前台点击了上一周
                3.queryDate的日期是周日的  表示用户在前台点击了下一周
         */
        // 获取当前时间
        Date date = DateUtil.date();
        if (StringUtils.isNotBlank(schedulingQueryDto.getQueryDate())){
            // 格式化用户传输过来的queryDate
            date = DateUtil.parse(schedulingQueryDto.getQueryDate(),"yyyy-MM-dd");
            // 使用DateUtil工具类判断用户传输过来的日期为周几 返回1表示周日 2表示周一
            int i = DateUtil.dayOfWeek(date);
            if (i==1){
                // TODO 如果是周日则表示要查询下一周的数据
                date = DateUtil.offsetDay(date,1);
            } else {
                // TODO 如果是周一表示要查询上一周的数据
                date = DateUtil.offsetDay(date,-1);
            }
        }
        // 使用DateUtil计算一周的开始日期和结束日期
        // 开始日期
        DateTime beginTime = DateUtil.beginOfWeek(date);
        // 结束日期
        DateTime endTime = DateUtil.endOfWeek(date);
        // 设置开始日期和结束日期到统一查询参数类
        schedulingQueryDto.setBeginDate(DateUtil.format(beginTime,"yyyy-MM-dd"));
        schedulingQueryDto.setEndDate(DateUtil.format(endTime,"yyyy-MM-dd"));
        //2.根据查询参数类查询数据库里医生的排班信息
        List<Scheduling> list = this.schedulingService.queryScheduling(schedulingQueryDto);
        //3.组装返回对象
        // (1)组装页面返回对象tableData
        List<SchedulingDto> schedulingDtos = new ArrayList<>();
        // 遍历需要排班的医生信息 一个医生对应三个排班信息 分别是上午 下午 晚上
        for (User user : users) {
            // 组装上午的医生排班信息
            SchedulingDto schedulingDto1 = new SchedulingDto(user.getUserId(),user.getDeptId(),"1",initMap(beginTime));
            // 组装下午的医生排班信息
            SchedulingDto schedulingDto2 = new SchedulingDto(user.getUserId(),user.getDeptId(),"2",initMap(beginTime));
            // 组装晚上的医生排班信息
            SchedulingDto schedulingDto3 = new SchedulingDto(user.getUserId(),user.getDeptId(),"3",initMap(beginTime));
            schedulingDtos.add(schedulingDto1);
            schedulingDtos.add(schedulingDto2);
            schedulingDtos.add(schedulingDto3);
            // 遍历医生的排班信息 设置医生的值班记录
            for (Scheduling scheduling : list) {
                // 获取数据库的医生id
                Long userId = scheduling.getUserId();
                String subsectionType = scheduling.getSubsectionType();// 获取排班时间段 1上午 2下午 3晚上
                String schedulingDay = scheduling.getSchedulingDay();// 获取医生的值班日期
                if (user.getUserId().equals(userId)){
                    switch (subsectionType){
                        case "1":
                            // 上午
                            // 给医生的值班记录赋值
                            Map<String, String> record1 = schedulingDto1.getRecord();
                            record1.put(schedulingDay,scheduling.getSchedulingType());
                            break;
                        case "2":
                            // 下午
                            // 给医生的值班记录赋值
                            Map<String, String> record2 = schedulingDto2.getRecord();
                            record2.put(schedulingDay,scheduling.getSchedulingType());
                            break;
                        case "3":
                            // 晚上
                            // 给医生的值班记录赋值
                            Map<String, String> record3 = schedulingDto3.getRecord();
                            record3.put(schedulingDay,scheduling.getSchedulingType());
                            break;
                        default:
                            break;
                    }
                }
            }
            // 把map转换成数组放到schedulingType中
            schedulingDto1.setSchedulingType(schedulingDto1.getRecord().values());
            schedulingDto2.setSchedulingType(schedulingDto2.getRecord().values());
            schedulingDto3.setSchedulingType(schedulingDto3.getRecord().values());
        }
        // (2)组装页面返回对象schedulingData
        Map<String,Object> schedulingData = new HashMap<>();
        schedulingData.put("startTimeThisWeek",DateUtil.format(beginTime,"yyyy-MM-dd"));
        schedulingData.put("endTimeThisWeek",DateUtil.format(endTime,"yyyy-MM-dd"));
        // (3)组装最终返回对象
        Map<String,Object> resMap = new HashMap<>();
        resMap.put("tableData",schedulingDtos);
        resMap.put("schedulingData",schedulingData);
        resMap.put("labelNames",initLabel(beginTime));
        return AjaxResult.success(resMap);
    }

    /**
     * 初始化labelNames
     * @param beginTime 一周的开始时间
     * @return
     */
    private String[] initLabel(DateTime beginTime) {
        String[] labelNames = new String[7];
        for (int i = 0; i < 7; i++) {
            DateTime dateTime = DateUtil.offsetDay(beginTime, i);
            labelNames[i] = DateUtil.format(dateTime,"yyyy-MM-dd")+formatterWeek(i);
        }
        return labelNames;
    }

    /**
     * 初始化周
     * @param i
     * @return
     */
    private String formatterWeek(int i) {
        switch (i){
            case 0:
                return "(周一)";
            case 1:
                return "(周二)";
            case 2:
                return "(周三)";
            case 3:
                return "(周四)";
            case 4:
                return "(周五)";
            case 5:
                return "(周六)";
            default:
                return "(周日)";
        }
    }

    /**
     * 初始化周一到周日的 值班记录
     * @param beginTime 当周的第一天日期
     * @return
     */
    private Map<String,String> initMap(DateTime beginTime) {
        // 如果此处使用hashMap可能会因为存取顺序不一致导致后期出问题
        // 所以此处使用LinkedHashMap来保证存储顺序一致
        Map<String,String> map = new LinkedHashMap<>();
        for (int i = 0; i < 7; i++) {
            // 获取周一到周日的每天日期
            DateTime d = DateUtil.offsetDay(beginTime, i);
            // 格式化日期
            String key = DateUtil.format(d,"yyyy-MM-dd");
            map.put(key,"");
        }
        return map;
    }

    /**
     * 保存排班数据
     */
    @PostMapping("saveScheduling")
//    @HystrixCommand
    public AjaxResult saveScheduling(@RequestBody SchedulingFormDto schedulingFormDto){
        schedulingFormDto.setSimpleUser(ShiroSecurityUtils.getCurrentSimpleUser());
        return AjaxResult.toAjax(this.schedulingService.saveScheduling(schedulingFormDto));
    }

}
